package com.zcsy.manage.distribution.common;

import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;

import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.fileupload.disk.DiskFileItem;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;
import org.springframework.web.multipart.commons.CommonsMultipartFile;

import com.aliyun.oss.OSSClient;
import com.aliyun.oss.model.GetObjectRequest;
import com.aliyun.oss.model.OSSObjectSummary;
import com.aliyun.oss.model.ObjectListing;
import com.zcsy.commons.constants.Constants;
import com.zcsy.commons.exception.ExceptionCode;
import com.zcsy.commons.exception.RunningException;
import com.zcsy.commons.model.RequestJson;
import com.zcsy.commons.upload.AliyunOssUtil;
import com.zcsy.commons.upload.BinaryDataUtil;
import com.zcsy.commons.upload.FTPUtil;
import com.zcsy.commons.upload.FileUtils;
import com.zcsy.commons.util.Globals;
import com.zcsy.commons.util.PropertiesUtil;

/**
 * @Title: UploaderController.java
 * @Package： com.zcsy.manage.web.common 
 * @Description: 附件上传、下载相关控制类
 * @author tanhuatang 786468449@qq.com
 * @Copyright: 2015 武汉中财数元信息技术有限公司 All rights reserved.
 * @date 2016年1月8日
 * @version 1.0
 * @see JDK1.7.0_75
 * @since
 */
@Controller
@RequestMapping(value = "/fileHandler")
public class UploaderController {
	
    
    private static final int IMG_STATE_SUCCESS  = 0;  //上传成功
    private static final int IMG_STATE_NON_TYPE = 1;  //图片类型错误
    private static final int IMG_STATE_OVERSIZE = 2;  //图片超过限定大小
    private static final int IMG_STATE_FAIL     = 3;  //图片上传失败
    
    
    private static PropertiesUtil propertiesUtil=new PropertiesUtil("config.properties");
    
    private static String endpoint = propertiesUtil.getProperty("OSS_ENDPOINT");
    private static String accessId= propertiesUtil.getProperty("ACCESS_ID");
    private static String accessKey= propertiesUtil.getProperty("ACCESS_KEY");
    private static String bucketName= propertiesUtil.getProperty("bucketName");
    private static String imageurl= propertiesUtil.getProperty("imageurl");
	static Log log = LogFactory.getLog(AliyunOssUtil.class);  
	
    /**
     * @Description 文件上传公共方法<br>
     * @param request 请求对象
     * @return map对象{(key-success,value-Boolean), (key-filePath, value-String)}
     * @author tanhuatang 786468449@qq.com
     * @date 2016年1月18日
     * @see
     */
    public Map<String, Object> uploadCommon(HttpServletRequest request) {
        Map<String, Object> map = new HashMap<String, Object>();
        
        OSSClient client = new  OSSClient(endpoint,accessId,accessKey); 
	        
        Boolean success = false;
        //文件输入流
        InputStream inputStream = null;
        //转换为文件请求
        MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request;
        //获取多文件
        Map<String, MultipartFile> fileMap = multipartRequest.getFileMap();
        //文件遍历上传
        for (Map.Entry<String, MultipartFile> entity : fileMap.entrySet()) {
            MultipartFile file = entity.getValue();
            //MultipartFile转File
            CommonsMultipartFile cf= (CommonsMultipartFile)file; 
            DiskFileItem fi = (DiskFileItem)cf.getFileItem(); 
            File f = fi.getStoreLocation();
            
            
            if (file != null && file.getSize() > 0) {
                try {
                    //获取文件输入流
                    //inputStream = file.getInputStream();
                    //上传至阿里云服务器
                    Map<String, Object> returnmap= AliyunOssUtil.uploadFile(client,bucketName, file.getOriginalFilename(),f);
                    System.out.println(file.getOriginalFilename());
                    map.put("success", returnmap.get("success"));
                    map.put("fileName",returnmap.get("objectkey"));
                    map.put("filePath",f.getPath());
                } catch (Exception e) {
                    e.printStackTrace();
                    map = null;
                } finally {
                    try {
                        //关闭文件输入流
                        if (inputStream != null) {
                            inputStream.close();
                        }
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
        return map;
    }
    
    /**
     * @Description 文件上传<br>
     * @param model 视图对象
     * @param request 请求对象
     * @param response 响应结果对象
     * @author tanhuatang 786468449@qq.com
     * @date 2016年1月11日
     * @see
     */
	@RequestMapping(value = "upLoaderMerge")
	@ResponseBody
	public void upLoaderMerge(Model model, HttpServletRequest request, HttpServletResponse response) {
	    Boolean success = false;
	    String fileIds = "";
	    String filePath = "";
	    //判断是否是multipart请求
	    if (ServletFileUpload.isMultipartContent(request)) {
	        try {
	            Map<String, Object> map = uploadCommon(request);
	            if (map != null) {
	                success = Boolean.valueOf(map.get("success").toString());
	                fileIds = map.get("fileName").toString();
	                filePath = map.get("filePath").toString();
	            }
	            //返回给服务端的内容
	            System.out.println("{\"status\":" + success + ",\"fileIds\":\"" + fileIds + "\"}");
	            response.getWriter().write("{\"status\":" + success + ",\"fileIds\":\"" + fileIds + "\"}");
	        } catch (Exception e) {
	            e.printStackTrace();
	            try {
                    response.getWriter().write("{\"status\":false,\"fileIds\":" + fileIds + ",\"filePath\":" + filePath+"}");
                } catch (IOException ioe) {
                    ioe.printStackTrace();
                }
	        }
	    }
	}
	
	/**
     * @Description 图文混排上传图片方法<br>
     * @param model 视图对象
     * @param request 请求对象
     * @param response 响应结果对象
     * @author chenshengfang 735569870@qq.com
     * @date 2016年1月11日
     * @see
     */
    @RequestMapping(value = "upLoaderMergeForUeditor")
    @ResponseBody
    public String upLoaderMergeForUeditor(Model model, HttpServletRequest request, HttpServletResponse response) {
        String filePath = "";
        //判断是否是multipart请求
        if (ServletFileUpload.isMultipartContent(request)) {
            Map<String, Object> map = uploadCommon(request);
                
            boolean success = (boolean)map.get("success");
            
//            if(success){
                
                filePath = (String)map.get("filePath");
//            }
        }
        
        return filePath;
    }
    
    /**
     * @Description 图文混排上传图片方法<br>
     * @param model 视图对象
     * @param request 请求对象
     * @param response 响应结果对象
     * @author chenshengfang 735569870@qq.com
     * @date 2016年1月11日
     * @see
     */
    @RequestMapping(value = "upLoaderForUeditor")
    @ResponseBody
    public String upLoaderForUeditor(Model model, HttpServletRequest request, HttpServletResponse response) {
    	String filePath = "";
    	//判断是否是multipart请求
    	if (ServletFileUpload.isMultipartContent(request)) {
    		Map<String, Object> map = uploadCommon(request);
    		filePath = (String)map.get("fileName");
    	}
    	return filePath;
    }
    
	/**
	 * @Description 检查文件的类型及大小<br>
	 * @param filename 文件名
	 * @param filesize 文件大小
	 * @return 图片检查结果
	 * @author tanhuatang 786468449@qq.com
	 * @date 2016年1月14日
	 * @see
	 */
	public int checkImage(String filename, long filesize) {
        String extend = filename.substring(filename.lastIndexOf(".") + 1);
        if (!"jpg".equalsIgnoreCase(extend) && !"png".equalsIgnoreCase(extend) 
            && !"bmp".equalsIgnoreCase(extend)) {
            return IMG_STATE_NON_TYPE;
        } else if (filesize > 1024 * 10000) {
            return IMG_STATE_OVERSIZE;
        } else {
            return IMG_STATE_SUCCESS;
        }
    }
	
	/**
	 * @Description 上传需要裁剪的原图片<br>
	 * @param request 请求对象
	 * @param response 结果对象
	 * @return Map对象:{key-state value:(0-成功;1-文件类型错误;2-文件超过限制大小;3-上传失败)}
	 * @author tanhuatang 786468449@qq.com
	 * @date 2016年1月14日
	 * @see
	 */
	@RequestMapping(value ="uploadCutImage")
    @ResponseBody
    public Map<String, Object> uploadLocalImage(HttpServletRequest request, HttpServletResponse response) {
	    int state = -1;
        Map<String, Object> map = new HashMap<String, Object>();
        MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest)request;
        //获取参数
        String imageId = request.getParameter("imageId");
        MultipartFile file = multipartRequest.getFile(imageId);
        
        if (file != null && file.getSize() > 0) {
            //文件验证
            state = checkImage(file.getOriginalFilename(), file.getSize());
            if (state == IMG_STATE_SUCCESS) {
                //获取工程所在目录
                String path = request.getSession().getServletContext().getRealPath("/");
                //判断目录是否存在，不存在就创建
                File tmpFile = new File(path + "/tmp/");
                //如果文件夹不存在则创建  
                if  (!tmpFile.exists()) {
                    tmpFile.mkdir();
                }
                //上传原图片
                File destFile = new File(tmpFile, file.getOriginalFilename());
                try {
                    file.transferTo(destFile);
                    map.put("logoUrl", "/tmp/" + file.getOriginalFilename());
                    map.put("originalUrl", destFile.getAbsolutePath());
                } catch (IllegalStateException e) {
                    e.printStackTrace();
                    state = IMG_STATE_FAIL;
                } catch (IOException e) {
                    e.printStackTrace();
                    state = IMG_STATE_FAIL;
                }
            }
        }
        map.put("state", state);
        return map;
    }
	
	/**
	 * @Description 上传裁剪后的图片<br>
	 * @param request 请求对象
	 * @param response 结果对象
	 * @return Map对象:{key-state value:(0-成功;1-文件类型错误;2-文件超过限制大小;3-上传失败)}
	 * @author tanhuatang 786468449@qq.com
	 * @date 2016年1月14日
	 * @see
	 */
	@RequestMapping(value ="uploadLogoImage" )
	@ResponseBody
	public Map<String, Object> uploadLogoImage(HttpServletRequest request,HttpServletResponse response) {
	    Map<String, Object> map = new HashMap<String, Object>();
	    OSSClient client = new  OSSClient(endpoint,accessId,accessKey); 
	    BufferedImage subImg;
	    String srcPath = request.getParameter("pic");
	    String uploadPath = request.getParameter("uploadPath");
	    String startX = request.getParameter("x");
	    String startY = request.getParameter("y");
	    String width = request.getParameter("w");
	    String height = request.getParameter("h");
	    //初始选区的值
	    String initX = request.getParameter("ix");
	    String initY = request.getParameter("iy");
	    String initW = request.getParameter("iw");
	    String initH = request.getParameter("ih");
	    String imageLogo = request.getParameter("imageLogo");
	    //根据type判断图片路径
	    String remoteFileDir = "";
	    int x = 0, y = 0, w = 0, h = 0;
	    int state = IMG_STATE_SUCCESS;

	    try {
	        Integer originalWidth = Integer.parseInt(request.getParameter("ow"));
	        Integer originalHeight = Integer.parseInt(request.getParameter("oh"));
	        remoteFileDir = "logoImg";//用户图片
	        //未设置选区时
	        if (width == null || height == null) {
	            //若初始选区宽高不为0，则将选取的图片宽高设为初始选区的宽高
	            if (initW != null && initH != null) {
	                //若初始选区边距不为0，则将选取的图片边距设为初始选区的宽高
	                if (initX != null && initY != null) {
	                    x = Integer.parseInt(initX);
	                    y = Integer.parseInt(initY);
	                }
	                w = Integer.parseInt(initW);
	                h = Integer.parseInt(initH);
	            } else {
	                //若初始选区也为0，则将选取的图片宽高都设为原图片的宽高
	                w = originalWidth;
	                h = originalHeight;
	            }
	        } else{
	            if(startX != null && startY != null){
	                x = Integer.parseInt(startX);
	                y = Integer.parseInt(startY);
	            }
	            w = Integer.parseInt(width);
	            h = Integer.parseInt(height);
	        }

	        File file = new File(srcPath);
	        if (file != null && originalWidth != null && originalHeight != null) {
	            //截取图片
	            BufferedImage bufImg = ImageIO.read(file);
	            Integer realX = x * bufImg.getWidth() / originalWidth;
	            Integer realY = y * bufImg.getHeight() / originalHeight;
	            Integer realW = w * bufImg.getWidth() / originalWidth;
	            Integer realH = h * bufImg.getHeight() / originalHeight;
	            subImg = bufImg.getSubimage(realX, realY, realW, realH);
	            //文件验证
	            state = checkImage(file.getAbsolutePath(), file.length());
	            if (state == IMG_STATE_SUCCESS) {
	                String fileExt = FileUtils.getExtend(file.getAbsolutePath());
	                String newFilename = FileUtils.getFileName(fileExt);
	                ImageIO.write(subImg, fileExt, file);
                    //String logoUrl = remoteFileDir + "/" + newFilename;
                    //图片上传至阿里云服务器
                    Map<String, Object> returnmap = AliyunOssUtil.uploadFile(client,bucketName, file.getName(),file); 
                    map.put("logoUrl",(String)returnmap.get("objectkey"));
	            }
	        }
	    } catch (Exception e) {
	        e.printStackTrace();
	        state = IMG_STATE_FAIL;
	    } finally {
            FileUtils.deleteFile(srcPath);
	    }
	    map.put("state", state);
	    return map;
	}
	
    /** 
     * 根据key删除OSS服务器上的文件 
    * @Title: deleteFile  
    * @Description:  
    * @param @param ossConfigure 
    * @param @param filePath    设定文件  
    * @return void    返回类型  
    * @throws 
     */  
    public static void deleteFile(OSSClient ossClient,String bucketName,String filePath){  
        ossClient.deleteObject(bucketName, filePath);  
          
    } 
	
	/**
	 * @Description 根据路径获取对应的文件<br>
	 * @param request 请求对象
	 * @param response 返回结果对象
	 * @param filePath 文件路径
	 * @param fileName 文件名(带后缀)
	 * @author tanhuatang 786468449@qq.com
	 * @date 2016年1月12日
	 * @see
	 */
	@RequestMapping(value="getFile")
	@ResponseBody
	public void getFile(final HttpServletRequest request, final HttpServletResponse response, 
	                    String filePath, String fileName) throws Exception {
	    if(filePath == null){
	        filePath = "";
	    }
	    String referer = request.getHeader("referer");
	    if (referer != null && referer.contains(Globals.getConfig("domainName"))) {
	        BinaryDataUtil.download(fileName, 
	            FTPUtil.httpDownload(Globals.getConfig("nginxFilePath") + filePath + fileName), request, response);
	    } else {
            RunningException.throwEx(ExceptionCode.FILE_ERROR, "该链接不存在!", request);
        }
	}
	
	/**
     * @Description 图文混排路径获取对应的文件方法<br>
     * @param request 请求对象
     * @param response 返回结果对象
     * @param filePath 文件路径
     * @param fileName 文件名(带后缀)
     * @author chenshengfang 735569870@qq.com
     * @date 2016年1月12日
     * @see
     */
    @RequestMapping(value="getFileForUeditor")
    @ResponseBody
    public void getFileForUeditor(final HttpServletRequest request, final HttpServletResponse response, 
                        String fileUrl) throws Exception {
        BinaryDataUtil.download(fileUrl, 
            FTPUtil.httpDownload(imageurl+fileUrl), request, response);
    }
	
	/**
	 * @Description 删除文件或目录<br>
	 * @param request 请求对象
	 * @param response 结果对象
	 * @param type 文件结构类型(1-文件,2-目录)
	 * @param filePath 文件(目录)路径
	 * @param fileName 文件名
	 * @return RequestJson结果对象
	 * @author tanhuatang 786468449@qq.com
	 * @date 2016年1月18日
	 * @see
	 */
	@RequestMapping(value="deleteFile")
	@ResponseBody
	public RequestJson deleteFile(final HttpServletRequest request, final HttpServletResponse response, 
	                              int type, String filePath, String fileName) {
	    RequestJson result = new RequestJson();
	    if (StringUtils.isNotBlank(filePath)) {
	        if (type == Constants.TYPE_FILE) {  //删除文件
	            if (StringUtils.isNotBlank(fileName)) {
    	            result.setSuccess(FTPUtil.deleteFile(Globals.getConfig("ftpServer"), 
                                       Integer.valueOf(Globals.getConfig("ftpPort")), 
                                       Globals.getConfig("ftpLoginName"), 
                                       Globals.getConfig("ftpPassword"), filePath, fileName));
	            } else result.setSuccess(false);
	        } else if (type == Constants.TYPE_DIRECTORY) {  //删除目录
	            result.setSuccess(FTPUtil.deleteDirectory(Globals.getConfig("ftpServer"), 
                                        Integer.valueOf(Globals.getConfig("ftpPort")), 
                                        Globals.getConfig("ftpLoginName"), 
                                        Globals.getConfig("ftpPassword"), filePath));
	        } else {
	            result.setSuccess(false);
	        }
	    }
	    return result;
	}
}